package com.sunburst.demo.actor.showcases.account;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Terminated;
import akka.event.LoggingAdapter;
import akka.pattern.Patterns;
import com.sunburst.demo.utils.ThreadUtils;
import scala.concurrent.Future;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.function.Consumer;

/**
 * 帐户应用
 *
 * @author sunburst
 */
public class AccountApp {

    public static void main(String[] args) {
        accountDemo();
    }


    /**
     * 银行帐户示例
     */
    public static void accountDemo() {
        LocalDateTime nowTime = LocalDateTime.now();

        ActorSystem accountAppAcotrSysTem = ActorSystem.create("accountApp");

        LoggingAdapter log = accountAppAcotrSysTem.log();


        // 银行
        ActorRef bankActorRef = accountAppAcotrSysTem.actorOf(AccountActor.create(new AccountDO("B308100005720000000", "银行", 0L, nowTime)), "BID0000000");

        // 公司
        ActorRef companyActorRef = accountAppAcotrSysTem.actorOf(AccountActor.create(new AccountDO("C30810000572888888", "公司", 0L, nowTime)), "CID0000000");

        // 员工
        ActorRef staffActorRef = accountAppAcotrSysTem.actorOf(AccountActor.create(new AccountDO("S308100005720000001", "员工", 0L, nowTime)), "SID0000001");

        // 消费者
        ActorRef userActorRef = accountAppAcotrSysTem.actorOf(AccountActor.create(new AccountDO("U308100005720000002", "消费者", 0L, nowTime)), "UID0000002");



        // 经济活动

        // 银行授信信用额度给公司
        bankActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "银行授信", "10000"), companyActorRef);

        ThreadUtils.sleep(Duration.ofSeconds(1L));

        // 银行授信信用额度给消费者
        bankActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "银行授信", "20000"), userActorRef);

        ThreadUtils.sleep(Duration.ofSeconds(3L));


        // 消费者购买商品
        userActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "消费", "10000"), companyActorRef);
        userActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "消费", "10000"), companyActorRef);

        ThreadUtils.sleep(Duration.ofSeconds(3L));


        // 公司发工资给员工
        companyActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "薪酬", "5000"), staffActorRef);
        companyActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "薪酬", "5000"), staffActorRef);

        ThreadUtils.sleep(Duration.ofSeconds(3L));


        // 员工存款到银行
        staffActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "存款", "5000"), bankActorRef);
        staffActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "存款", "5000"), bankActorRef);

        ThreadUtils.sleep(Duration.ofSeconds(1L));


        // 公司还款到银行
        companyActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "还款", "10000"), bankActorRef);

        // 公司存款到银行
        companyActorRef.tell(new AccountCmd(AccountCmdTypeEnum.TRANSFER_OUT, "存款", "10000"), bankActorRef);


        ThreadUtils.sleep(Duration.ofSeconds(1L));


        // 帐户查询


        // 银行
        Patterns.ask(bankActorRef, new AccountCmd(AccountCmdTypeEnum.QUERY, "", ""), Duration.ofSeconds(3L)).thenAccept(new Consumer<Object>() {

            @Override
            public void accept(Object o) {
                log.info("==== Patterns.ask: {} ", o);
            }

            @Override
            public Consumer<Object> andThen(Consumer<? super Object> after) {
                return Consumer.super.andThen(after);
            }

        });


        // 消费者
        Patterns.ask(userActorRef, new AccountCmd(AccountCmdTypeEnum.QUERY, "", ""), Duration.ofSeconds(3L)).thenAccept(new Consumer<Object>() {

            @Override
            public void accept(Object o) {
                log.info("==== Patterns.ask: {} ", o);
            }

            @Override
            public Consumer<Object> andThen(Consumer<? super Object> after) {
                return Consumer.super.andThen(after);
            }

        });


        // 公司
        Patterns.ask(companyActorRef, new AccountCmd(AccountCmdTypeEnum.QUERY, "", ""), Duration.ofSeconds(3L)).thenAccept(new Consumer<Object>() {

            @Override
            public void accept(Object o) {
                log.info("==== Patterns.ask: {} ", o);
            }

            @Override
            public Consumer<Object> andThen(Consumer<? super Object> after) {
                return Consumer.super.andThen(after);
            }

        });


        // 员工
        Patterns.ask(staffActorRef, new AccountCmd(AccountCmdTypeEnum.QUERY, "", ""), Duration.ofSeconds(3L)).thenAccept(new Consumer<Object>() {

            @Override
            public void accept(Object o) {
                log.info("==== Patterns.ask: {} ", o);
            }

            @Override
            public Consumer<Object> andThen(Consumer<? super Object> after) {
                return Consumer.super.andThen(after);
            }

        });



        // 结束
        Future<Terminated> terminateFuture = accountAppAcotrSysTem.terminate();

        ThreadUtils.sleep(Duration.ofSeconds(10L));

        log.info("==== terminateFuture.isCompleted: {} ", terminateFuture.isCompleted());
    }

}
